做到這裡,Data Machi 已經可以選擇工具、跨來源查詢,也開始能處理一段完整的工作流程。但只要使用者開始多輪追問,新的問題就會出現:系統到底應該記住多少資訊?
假設使用者第一句問:「今年哪一類工單最多?」系統查詢後得到 Delivery Issue。下一句使用者只說:「那去年呢?」如果 Agent 完全沒有記憶,它甚至不知道「那」指的是哪一個問題;但另一個極端,是把所有歷史訊息、Tool Result 與模型回答無限塞回 Prompt,這樣不只會增加 Token、成本與等待時間,也可能讓過去已經失效的資訊干擾現在的判斷。
因此 Memory 真正要解決的問題不是「如何把所有東西記住」,而是:
現在這一輪工作真正需要哪些上下文?哪些資訊可以安全沿用?哪些資訊雖然以前查過,但現在必須重新確認?
整體可以先理解成:
談到 AI Memory 時,很容易直接想到 Conversation History,也就是把前面所有使用者與模型的對話重新放進下一次 Prompt。但企業 Agent 真正需要的 Memory 往往不只一種,而且不同資訊的用途完全不同。
至少可以先區分三類。
| Memory 類型 | 主要用途 | 例子 |
|---|---|---|
| Recent Conversation | 理解近期追問、代名詞與上下文 | 「那去年呢?」中的「那」 |
| Summary Memory | 壓縮較長對話,保留核心任務背景 | 目前正在分析工單趨勢 |
| Tool Result Memory | 保存真正查詢回來的事實 | Google Sheets 查到的數字 |
Recent Conversation 比較偏向「理解語言」,例如知道「那個市場」、「剛才那個專案」到底指的是什麼;Summary Memory 則是在對話變長後,保留真正仍然有用的背景,避免一直把數十輪聊天全部送回模型;Tool Result Memory 則完全不同,它保存的是外部系統真正查詢回來的資料。
這三者如果全部混成一段自然語言,很快就會產生一個問題:
這句話到底是使用者說的、模型推測的,還是 Tool 真正查到的?
因此企業 Agent 的 Memory 最好不是只有一個「聊天紀錄」欄位,而是依照資訊性質分開管理。
多輪對話的第一個基礎,是每一段對話都有明確的 Conversation ID。Backend 收到新訊息時,應該只讀取這一段對話需要的上下文,而不是把同一個使用者過去所有工作一次載入。
例如:
Conversation ID:
conv_001
User:
今年哪一類工單最多?
Result:
Delivery Issue
下一輪:
Conversation ID:
conv_001
User:
那去年呢?
Coordinator 就知道這句追問屬於前一個任務。
但如果另一段對話是:
Conversation ID:
conv_002
User:
幫我整理昨天會議的 Action Items
兩段工作就不應該共享相同的短期 Context。
這對多人環境更重要。如果 Conversation、Session 或 User Context 沒有隔離好,就可能發生 A 使用者的查詢結果被 B 使用者沿用,這不只是回答錯誤,而可能直接變成資料權限問題。
因此 Memory 的第一條原則不是「記住」,而是:
先確認這份記憶到底屬於誰、哪一段 Conversation,以及哪一個工作任務。
Recent Conversation 的主要用途,是讓 Agent 理解使用者沒有重複講完整條件的追問。
例如第一輪:
「2026 年 7 月台灣共有多少筆需求?」
系統取得:
Period:
2026-07
Market:
Taiwan
Request Count:
328
第二輪使用者只問:
「那其中完成的呢?」
這句話真正代表的是:
沿用:
Period = 2026-07
Market = Taiwan
新增條件:
Status = Completed
如果沒有前文,這個問題根本無法獨立理解。
因此 Recent Conversation 不一定需要保存很長。只要能讓 Coordinator 正確解讀目前的省略語句、代名詞與延續條件,就已經發揮作用。
但要注意,「理解前文」不代表「直接沿用前一個答案」。在這個例子中,因為使用者增加了 Status = Completed,仍然需要重新查詢 Data Tool,只是查詢條件可以從前文延續。
這也是 Memory 與 Cache 很容易被混淆的地方:記住條件,不代表一定沿用結果。
如果一段 Conversation 已經進行了 30 輪,每次都把所有訊息完整送進模型,Prompt 很快就會膨脹。
這時可以使用 Summary Memory,把較長對話整理成一份較精簡的工作背景。例如前面可能經過十幾輪討論:
使用者正在分析 2026 年需求工單。
已確認:
- 目前分析範圍為 Taiwan 與 Hong Kong
- 主要關注 Delivery Issue
- 使用者希望比較 2025 與 2026
- 數據來源為 Google Sheets
- 定義來源為 Customer Service Taxonomy.pdf
這份 Summary 的目標不是保存每一句話,而是保留後面仍然會影響工作的資訊。
可以把它理解成:
完整對話
↓
抽取仍然重要的工作背景
↓
Summary Memory
如果前面有一段閒聊、重複確認或已經失效的條件,就不需要永久留在 Summary 中。
因此好的 Summary Memory 應該不斷回答:
哪些資訊之後還會影響下一步?
而不是:
「怎麼把整段聊天縮短一點?」
第三類 Memory 是 Data Machi 特別重要的一層:Tool Result Memory。
假設 Google Sheets Tool 查詢:
Query:
Year = 2026
Market = Taiwan
Metric = Request Count
得到:
Request Count = 328
如果只讓模型回答:
「2026 年台灣共有約 330 筆需求。」
然後 Memory 裡只留下這句自然語言,後面就會失去原始精度。
更理想的方式,是保存:
Tool:
google_sheets
Query:
year = 2026
market = Taiwan
metric = request_count
Raw Result:
328
Source:
ticket_data
Queried At:
2026-09-01T21:30:00+08:00
這樣下一輪如果使用者說:
「台灣比香港多幾 %?」
Coordinator 可以使用真正的 328 進行計算,而不是使用模型先前說的「約 330」。
因此對數字、日期、人名、狀態與 ID 這類事實,應該遵守一個原則:
原始 Tool Result 是事實層,模型整理後的回答只是 Presentation Layer。
這也是 Memory 很容易出現的一個風險。
假設第一輪模型錯誤地回答:
「專案截止日期是 9 月 30 日。」
即使 Tool 原始結果其實沒有 Deadline,如果下一輪系統只是把前面的 Assistant Message 當成 Memory,就可能開始把「9 月 30 日」視為既定事實。
第三輪使用者再問:
「距離 Deadline 還有幾天?」
系統甚至可能繼續用這個錯誤資訊計算。
因此最好把 Conversation Message 與 Tool Result 分開:
Conversation
├─ User Message
├─ Assistant Message
│
└─ Tool Results
├─ Tool Name
├─ Query
├─ Raw Result
├─ Source
└─ Queried At
如果 Assistant Message 和 Tool Result 不一致,後續應該優先相信可驗證的 Source,而不是模型曾經說過什麼。
這能避免 Memory 逐漸把一次生成錯誤放大成後續多輪對話中的「假事實」。
Memory 真正困難的地方,不是保存,而是決定Reuse 還是 Re-query。
例如前一輪已經從 PDF 找到:
「Delivery Issue 是指配送延遲、缺件與配送狀態異常。」
下一輪使用者說:
「可以用比較簡單的方式解釋嗎?」
這時通常可以沿用既有 Document Result,因為使用者只是修改表達方式。
Existing Document Result
↓
Reuse
↓
Simplify wording
再例如:
「幫我整理成三點。」
或:
「換成英文。」
這些也屬於 Presentation Change,通常不需要重新查 Source。
可以先整理成:
| 使用者要求 | 建議行為 |
|---|---|
| 換成英文 | 沿用結果 |
| 整理成表格 | 沿用結果 |
| 縮短成三點 | 沿用結果 |
| 用簡單方式解釋 | 沿用結果 |
| 引用剛才的來源 | 沿用已保存 Metadata |
這些操作不改變事實條件,因此重新查詢通常只會增加成本與不一致風險。
另一類情況則不應直接依賴舊 Result。
例如:
「現在專案進度呢?」
「今天銷售多少?」
「最新庫存呢?」
這類問題中的資料本身會隨時間變動。
即使前一輪五分鐘前才查過,使用者如果明確要求:
「再查一次最新狀態。」
系統也應該重新查 Source of Truth。
可以用兩個問題快速判斷:
只要其中一個答案是「是」,就應該提高 Re-query 的優先級。
例如:
| 資料 | 一般新鮮度 |
|---|---|
| 公司政策定義 | 相對穩定 |
| 歷史報告 | 穩定 |
| KPI Definition | 相對穩定 |
| 專案狀態 | 可能快速變動 |
| 庫存 | 高度動態 |
| 今日銷售 | 高度動態 |
| 工單狀態 | 持續變動 |
因此 Memory 不只要知道「以前查過什麼」,也要知道:
這個結果現在還新鮮嗎?
可以把 Tool Result 想成超市裡不同保存期限的食品。有些資料可以放很久,有些很快就過期。
例如:
Policy Definition
TTL = 24 hours
或:
Project Status
TTL = 5 minutes
又或者:
Inventory
TTL = 1 minute
這裡的 TTL(Time To Live)只是示意,不代表所有企業都應該使用相同數字。真正應該根據資料更新頻率、業務風險與使用者對即時性的期待決定。
例如一份每季才更新的政策文件,沒有必要每 30 秒重新查一次;但物流狀態或庫存,如果沿用昨天的 Result 回答「現在還有多少」,就很容易造成錯誤。
因此可以把 Reuse 判斷整理成:
有舊 Result?
↓
是否仍在有效期限?
↓
┌──────────────┬──────────────┐
│ 是 │ 否 │
│ │ │
│使用者要求最新?│重新查詢 │
└──────────────┴──────────────┘
↓
┌──────────────┬──────────────┐
│ 是 │ 否 │
│ │ │
│重新查詢 │安全沿用 │
└──────────────┴──────────────┘
這樣 Memory 才不會變成另一種 Cache Bug。
現在回到最一開始的例子。
第一輪:
「今年哪一類工單最多?」
Tool Result:
Period:
2026
Top Category:
Delivery Issue
Count:
328
第二輪:
「那去年呢?」
Coordinator 不應該直接沿用:
Delivery Issue = 328
因為使用者修改的是時間條件。
它應該從 Memory 中取出:
Original Task:
找出工單最多的 Category
Original Period:
2026
再重新組成:
Task:
找出工單最多的 Category
Period:
2025
然後重新呼叫 Data Tool。
所以這一輪真正沿用的是:
問題結構與其他條件。
而不是:
舊的數據結果。
這個差異很重要。
第一輪:
「今年哪一類工單最多?」
得到:
Top Category:
Delivery Issue
下一輪使用者問:
「那它的定義呢?」
這次 Memory 要解決的是代名詞:
它
=
Delivery Issue
接著 Coordinator 判斷,這是一個文件知識問題,因此呼叫:
search_documents(
query="Delivery Issue definition"
)
這就是 Memory 與 Coordinator 合作的地方。
Memory 提供:
目前使用者指的是誰 / 什麼條件
Coordinator 則決定:
下一步應該用哪個 Tool
如果前一輪已經有:
Top Category:
Delivery Issue
Definition:
...
Project Status:
In Progress
使用者下一句只是:
「幫我整理成三點。」
這時 Coordinator 應該直接使用 Existing Results:
Existing Results
↓
Reformat
↓
3 Bullet Points
而不是重新執行:
Sheets
→ Document
→ Project
這不只是節省 API Call,也能保持 Conversation Consistency。
如果要驗證 Data Machi 的 Memory 是否開始真正工作,不需要一開始就做很複雜的 Long-term Memory。先把三種最常見追問做好,就已經非常有價值。
第一輪:
「2026 年 7 月共有多少筆需求?」
第二輪:
「那 6 月呢?」
應該:
沿用:
Metric = Request Count
其他 Scope
修改:
Month = June
→ Re-query
第一輪:
「哪一類需求最多?」
第二輪:
「那它的定義呢?」
應該:
沿用:
Top Category
切換 Tool:
Data Tool → Document Tool
第一輪:
「哪個市場問題最多?相關專案如何?」
第二輪:
「幫我整理成三點。」
應該:
Reuse Existing Results
→ 不重新查詢
如果這三類都能穩定處理,Memory 就已經不只是「保存聊天紀錄」,而是真正開始參與工作上下文的管理。
實際測試時,可以設計一段固定 Conversation。
「2026 年 7 月台灣共有多少筆需求?」
系統應該正常查詢 Data Tool,並把 Query Conditions 與 Result 存進目前 Conversation State。
「那其中完成的呢?」
Coordinator 應該理解:
Period = 2026-07
Market = Taiwan
Status = Completed
並重新查詢。
「那另一個呢?」
如果目前上下文無法確定「另一個」指市場、Category 還是 Status,就應該 Clarify,而不是自行猜測。
「我剛更新資料了,再查一次最新結果。」
即使上一個 Result 還存在 Memory,系統也應該:
force_refresh = true
重新呼叫 Source Tool。
這四輪分別測試:
Context Resolution
Condition Reuse
Clarification
Freshness / Re-query
如果全部正常,Memory 才真的開始支援工作流程。
Memory 並不是越多越好。
如果每一輪都把完整對話、所有 Tool Results、所有模型回答全部送回模型,Prompt 會越來越長。結果可能是:
例如 Conversation 已經從 Taiwan 切換到 Hong Kong,但早期大量 Taiwan 資訊仍然存在 Prompt,就可能造成新的 Query Parameter 判斷錯誤。
另一個極端是只保存最後一句訊息。
使用者問:
「那去年呢?」
系統只能看到:
Current Message:
那去年呢?
完全不知道前面在比較什麼,就只能要求使用者重講一次。
這會讓多輪對話失去價值。
因此好的 Memory 策略不是:
Remember Everything
也不是:
Remember Nothing
而是:
保留仍然影響任務的資訊
+
需要時重新取得事實
如果系統把不同 Conversation ID 的 Memory 混在一起,會產生非常難察覺的錯誤。
例如:
Conversation A
Market = Taiwan
另一段:
Conversation B
Market = Hong Kong
使用者在 Conversation B 問:
「那去年呢?」
結果系統錯誤抓到 Conversation A 的 Context,就可能跑去查 Taiwan。
因此 Memory Key 至少可能需要包含:
User ID
+
Conversation ID
如果工作權限更複雜,還可能需要:
Organization
Workspace
Session
這也是為什麼 Memory 在企業產品裡不只是 LLM Feature,同時也是資料與權限架構的一部分。
前幾天我們已經開始多次提到 State。其實目前整理的很多 Memory 資訊,之後都可以成為 LangGraph State 的一部分。
例如:
State
├─ current_question
├─ conversation_id
├─ recent_context
├─ task_summary
├─ query_conditions
├─ tool_results
├─ sources
├─ queried_at
├─ missing_information
└─ task_status
當 Workflow 執行時,不同 Node 可以讀取需要的 State,再把新結果寫回去。
例如:
Coordinator Node
↓
讀取 recent_context
↓
理解「那去年呢?」
↓
更新 query_conditions
↓
Data Tool Node
↓
重新查詢
↓
更新 tool_results
這樣 Memory 不再只是聊天介面的一個功能,而會成為整個 Agent Workflow 中的一部分。
使用者通常最容易發現的一種錯誤,就是:
「我明明叫你查現在最新狀態,你卻回答昨天的資料。」
這種錯誤會非常傷信任。
因此只要使用者出現:
這類語句時,Coordinator 都應該提高 Re-query 的優先級。
例如:
User:
「目前 Project Status 呢?」
Existing Memory:
Status = In Progress
Queried At = 3 days ago
這時不應該直接沿用。
而是:
Project Tool
→ Re-query
→ Updated Status
好的 Memory 不是讓 AI 少查資料,而是:
讓 AI 知道什麼時候可以不用重做,以及什麼時候絕對不能偷懶。
今天的重點:
好的 Memory 不是「記得越多越好」,而是把不同用途的 Context 分開管理:近期對話用來理解追問,Summary 保留長任務背景,Tool Result 保存可驗證的事實。真正重要的是知道什麼可以沿用、什麼需要修改條件後重新查詢,以及什麼資訊已經過期,不能再當成現在的答案。
下一篇,我們會處理另一個很真實的問題:當資訊不足時,Agent 到底應該自己再查一次,還是先問使用者? 這會帶我們進入 Clarification,也就是讓 Agent 知道什麼時候「不要猜」。
我們下集見囉!